﻿using System.IO;
using System.Text;

namespace IniFileManager
{
	/// <summary>
	/// Class enabling library user loading/saving ini file from/to IniData structure.
	/// </summary>
	public static class IniParser
	{
		/// <summary>
		/// CreateElementFromString provides to loading ini file.
		/// </summary>
		/// <param name="stream">Stream with ini file, we want load.</param>
		/// <param name="options">Option which say, how manager should behave, if data are not written correctly.</param>
		/// <param name="schema">Schema which say how ini file should be like.</param>
		/// <returns>IniData class holding all information of ini file.</returns>
		public static IniData LoadIni( Stream stream, IniLoadOptions options, IniSchema schema )
		{
			var source = new StreamReader( stream );
			return LoadIniFromTextReader( source, options, schema );
		}

		/// <summary>
		/// CreateElementFromString provides to loading ini file.
		/// </summary>
		/// <param name="fileStream">Stream with ini file, we want load.</param>
		/// <param name="options">Option which say, how manager should behave, if data are not written correctly.</param>
		/// <param name="schema">Schema which say how ini file should be like.</param>
		/// <returns>IniData class holding all information of ini file.</returns>
		public static IniData LoadIni( FileStream fileStream, IniLoadOptions options, IniSchema schema )
		{
			var source = new StreamReader( fileStream );

			return LoadIniFromTextReader( source, options, schema );
		}

		/// <summary>
		/// CreateElementFromString provides to loading ini file.
		/// </summary>
		/// <param name="str">String with ini file, we want load.</param>
		/// <param name="options">Option which say, how manager should behave, if data are not written correctly.</param>
		/// <param name="schema">Schema which say how ini file should be like.</param>
		/// <returns>IniData class holding all information of ini file.</returns>
		public static IniData LoadIni( string str, IniLoadOptions options, IniSchema schema )
		{
			var source = new StringReader( str );
			return LoadIniFromTextReader( source, options, schema );
		}

		/// <summary>
		/// Method whick saves IniData structure to file stream in ini file format.
		/// </summary>
		/// <param name="fileStream">Output stream.</param>
		/// <param name="data">Input data.</param>
		public static void SaveIni( FileStream fileStream, IniData data )
		{
			StreamWriter writer = new StreamWriter( fileStream );

			SaveIniToTextWriter( data, writer );
		}

		/// <summary>
		/// Method whick saves IniData structure to stream in ini file format.
		/// </summary>
		/// <param name="stream">Output stream.</param>
		/// <param name="data">Input data.</param>
		public static void SaveIni( Stream stream, IniData data )
		{
			StreamWriter writer = new StreamWriter( stream );

			SaveIniToTextWriter( data, writer );
		}

		/// <summary>
		/// Method whick saves IniData structure to string in ini file format.
		/// </summary>
		/// <param name="str">Output string.</param>
		/// <param name="data">Input data.</param>
		public static void SaveIni( out string str, IniData data )
		{
			StringBuilder output = new StringBuilder();
			StringWriter writer = new StringWriter( output );

			SaveIniToTextWriter( data, writer );

			str = output.ToString();
		}

		/// <summary>
		/// CreateElementFromString provides to loading ini file.
		/// </summary>
		/// <param name="source">TextReader with ini file, we want load.</param>
		/// <param name="options">Option which say, how manager should behave, if data are not written correctly.</param>
		/// <param name="schema">Schema which say how ini file should be like.</param>
		/// <returns>IniData class holding all information of ini file.</returns>
		public static IniData LoadIniFromTextReader( TextReader source, IniLoadOptions options, IniSchema schema )
		{
			IniLoadingContext loadContext = new IniLoadingContext( source, options, schema );

			return loadContext.LoadIni();
		}

		/// <summary>
		/// Method whick saves IniData structure to text writer in ini file format.
		/// </summary>
		/// <param name="data">Input data.</param>
		/// <param name="target">Output textwriter.</param>
		public static void SaveIniToTextWriter( IniData data, TextWriter target )
		{
			data.FileStructure.WriteSelf( target );
		}
	}
}